package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.dto.SkuDTO;
import com.leyou.dto.SpuDTO;
import com.leyou.dto.SpuDetailDTO;
import com.leyou.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import org.bouncycastle.cms.PasswordRecipientId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpuDetailService spuDetailService;

    @Override
    public PageDTO<SpuDTO> queryBypage(Integer brandId, Integer categoryId, Integer id, Integer page, Integer rows, Boolean saleable) {

        //先查询spu表
        //分页查询
        //分页查询保证健壮性
        int min = Math.min(page, 100);
        int max = Math.max(rows, 5);
        //分页查询条件构造
        Page<Spu> fenye = this.query().eq(brandId!=null,"brand_id", brandId)
                .eq(categoryId!=null,"cid3", categoryId)
                .eq(id!=null,"id", id)
                .eq(saleable!=null,"saleable", saleable)
                .page(new Page<>(min, max));
        //取出total
        //取出totalsize
        //取出Page《spu》
        long total = fenye.getTotal();
        long pages = fenye.getPages();
        List<Spu> records = fenye.getRecords();
        //转化为dto
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(records);
        //循环dto对象，创建方法加入brandname和categoryname
        for (SpuDTO spuDTO : spuDTOS) {
            //定义方法
            handleinput(spuDTO);
        }
        //创建一个分页对象返回给前端
        return new PageDTO<SpuDTO>(total, pages, spuDTOS);
    }

    @Transactional
    @Override
    public void inputcategory(SpuDTO spuDTO) {
        //关联的分类和品牌都是已经有的
        //无需改动
        //商品新增
        //改动了共有属性，比如新增mate40系列
        //改变了spu和spu_detail
        //改变了具体的商品个体
        //比如华为mate40系列清新绿
        //所以改变了Sku表单
        //spu,Spu_detail,三表改变
        //先改变spu表
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean save = this.save(spu);
        if (!save) {
            throw new LyException(500, "新增商品失败~~~~");
        }
        //新增spu_detail
        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        SpuDetail spuDetail1 = spuDetail.toEntity(SpuDetail.class);
        spuDetail1.setSpuId(spu.getId());
        boolean save1 = spuDetailService.save(spuDetail1);
        if (!save1) {
            throw new LyException(500, "新增商品详情失败~~~");
        }
        //新增sku表单
        List<Sku> collect = spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
        //批量增加
        skuService.saveBatch(collect);

    }

    @Override
    public void updatecatestatus(Long id, Boolean saleable) {
        //先更新spu表，再更新相关联的sku表单
        //两种方式修改
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean b = this.updateById(spu);
        if (!b) {
            throw new LyException(500, "更新失败~~~");
        }
        //更新sku表单
        boolean update = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!update) {
            throw new LyException(500, "更新sku表单失败~~~~");
        }
    }

    @Override
    public SpuDTO queryBypathId(Long id) {
        //根据spuid查询
        Spu id1 = this.query().eq("id", id).one();
        //第二种方式    Spu byId = this.getById(id);
        //getById
        //再差detail和sku表单
        SpuDetail spu_id = spuDetailService.query().eq("spu_id", id).one();
        //第二种方式    SpuDetail byId = spuDetailService.getById(id);
        //getById
        SpuDetailDTO spuDetailDTO = new SpuDetailDTO(spu_id);
        List<Sku> spu_id1 = skuService.query().eq("spu_id", id).list();
        List<SkuDTO> collect = spu_id1.stream().map(SkuDTO::new).collect(Collectors.toList());
        //categoryName商品分类名称拼接
        //brandName品牌名称
        SpuDTO spuDTO = new SpuDTO(id1);
        spuDTO.setSpuDetail(spuDetailDTO);
        spuDTO.setSkus(collect);
        handleinput(spuDTO);
        return spuDTO;


    }

    @Override
    @Transactional
    public void updateCategory(SpuDTO spuDTO) {
        //判断是否存在spu
        //请求中有spu的id
        //如果请求中带来了spu的id值
        //说明后台需要根据这个带来的spu的id值找到匹配到的id值的
        //一个spu对象
        //然后匹配到以后，拿到请求体中的数据，根据id值匹配到的spu
        //用请求体中的数据对这个匹配到的spu进行修改更新
        //所以先判断是否有spuid
        //再判断是否有spu_detail的id值
        //最后判断是否有sku的id值
        //有id值，saleable=false为删除
        //有skuid，没有saleable=false为修改更新
        //没有skuid，则为主键自增，则为新增
        //三大判断
        //首先spu的id值判断
        Spu spu = spuDTO.toEntity(Spu.class);
        Long id = spuDTO.getId();
        if (id != null) {
            //修改spu
            boolean b = this.updateById(spu);
            if (!b) {
                throw new LyException(500, "更新商品失败~~");
            }
        }
        //再判断是否有spu_detail的id值
        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        if (spuDetail != null && spuDetail.getSpuId() != null) {
            //更新spudetail
            SpuDetail spuDetail1 = spuDetail.toEntity(SpuDetail.class);
            boolean ddd = spuDetailService.updateById(spuDetail1);
            if (!ddd) {
                throw new LyException(500, "更新商品失败~~~");
            }
        }
        //判断是否有sku的id值
        List<SkuDTO> skus = spuDTO.getSkus();
        if (!CollectionUtils.isEmpty(skus)) {
            //直接结束方法返回
            return;
        }
        //不是null
        //判断
        //现根据soudto中的saleable是否为null来进行分组
        Map<Boolean, List<Sku>> collect = skus.stream().map(skuDTO -> {
            return skuDTO.toEntity(Sku.class);
        }).collect(Collectors.groupingBy(sku -> {
            return sku.getSaleable() == null;
        }));
        //通过true，false分类
        //SALEABLE为null
        //没有把下架信息为falsevar传给后台,不下架再删除就是新增和修改
        List<Sku> skus1 = collect.get(true);
        if (!CollectionUtils.isEmpty(skus1)) {
            skuService.saveOrUpdateBatch(skus1);

        }
        //获取要删除的list
        List<Sku> skus2 = collect.get(false);
        if (!CollectionUtils.isEmpty(skus2)) {
            List<Long> collect1 = skus2.stream().map(Sku::getId).collect(Collectors.toList());
            skuService.removeByIds(collect1);
        }
    }

    public void handleinput(SpuDTO spuDTO) {
        //增加brandId和categoryName
        Long brandId = spuDTO.getBrandId();
        Brand object = brandService.query().eq("id", brandId).one();
        if (object != null) {
            String name = object.getName();
            spuDTO.setBrandName(name);
        }
        //根据ids查询出所有的cid1，cid2，cid3
        List<Long> categoryIds = spuDTO.getCategoryIds();
        List<Category> categories = categoryService.listByIds(categoryIds);
        //用流方式赋予“/”
        //列表中循环取出name。然后用“/”拼接
        if (!CollectionUtils.isEmpty(categories)) {
            String collect = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(collect);
        }

    }
}
